package me.atbar.moonlib.builder;

import lombok.NonNull;
import me.atbar.moonlib.control.EnchantAdder;
import me.atbar.moonlib.util.SkullUtils;
import me.atbar.moonlib.control.UMaterial;
import me.atbar.moonlib.util.ColorUtils;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.banner.Pattern;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author AtBar
 * @since 2020.03.26
 */
public class ItemBuilder {

    private ItemStack item;
    private ItemMeta meta;

    public ItemBuilder(Material material) {
        this.item = UMaterial.valueOf(material.toString()).getItemStack();
        this.meta = item.getItemMeta();
    }

    /**
     * It only uses in 1.12 and below
     *
     * @param material Item material
     * @param data Item Data
     */
    public ItemBuilder(Material material, int data) {
        this.item = UMaterial.valueOf(material.toString(), (byte) data);
        if(item == null) {
            this.item = UMaterial.valueOf(material.toString()).getItemStack();
            this.meta = item.getItemMeta();
            return;
        }
        this.meta = item.getItemMeta();
    }

    public ItemBuilder name(String name) {
        this.meta.setDisplayName(name);
        return this;
    }

    public ItemBuilder lore(String... lore) {
        List<String> loreList = Arrays.asList(lore);
        this.meta.setLore(loreList);
        return this;
    }

    public ItemBuilder color() {
        if(this.meta == null) {
            return this;
        }
        if(this.meta.getLore() == null) {
            return this;
        }
        if(this.meta.hasDisplayName()) {
            this.meta.setDisplayName(ColorUtils.color(this.meta.getDisplayName()));
        }
        if(this.meta.hasLore()) {
            this.meta.getLore().forEach(lore -> {
                this.meta.getLore().remove(lore);
                this.meta.getLore().add(ColorUtils.color(lore));
            });
            this.meta.setLore(this.meta.getLore());
        }
        return this;
    }

    public ItemBuilder setNumber(int amount) {
        this.item.setAmount(amount);
        return this;
    }

    public ItemBuilder addEnchantment(Enchantment enchantments, Integer level) {
        this.item.addUnsafeEnchantment(Objects.requireNonNull(EnchantAdder.matchXEnchantment(enchantments).parseEnchantment()), level);
        return this;
    }

    public ItemBuilder setUnbreakable(boolean isUnbreakable) {
        this.meta.setUnbreakable(isUnbreakable);
        return this;
    }

    /**
     * 减少耐久度
     *
     * @param amount 减少的数额
     * @return The Builder
     */
    public ItemBuilder removeDurability(int amount) {
        if(this.item.getDurability() == 0) {
            return this;
        }
        short add = (short) (this.item.getDurability() - amount);
        this.item.setDurability(add);
        return this;
    }

    /**
     * 添加耐久度
     *
     * @param amount 添加的数额
     * @return The Builder
     */
    public ItemBuilder addDurability(int amount) {
        if(this.item.getDurability() == 0) {
            return this;
        }
        this.item.setDurability((short) amount);
        return this;
    }

    public ItemBuilder addItemFlags(ItemFlag... itemFlags) {
        this.meta.addItemFlags(itemFlags);
        return this;
    }

    public ItemBuilder skull(String playerName) {
        if(this.item.getType() == UMaterial.PLAYER_HEAD_ITEM.getMaterial()) {
            this.meta = SkullUtils.applySkin(meta, playerName);
        }
        return this;
    }

    public ItemBuilder addPatterns(Pattern... patterns) {
        if(isType(ItemSpecial.BANNER.get())) {
            return this;
        }
        for (Pattern pattern : patterns) {
            ((BannerMeta) meta).addPattern(pattern);
        }
        return this;
    }

    public ItemBuilder addPattern(Pattern pattern) {
        if(isType(ItemSpecial.BANNER.get())) {
            return this;
        }
        ((BannerMeta) meta).addPattern(pattern);
        return this;
    }

    public ItemBuilder addBookRecipe(NamespacedKey... keys) {
        if(isType(ItemSpecial.KNOWLEDGE_BOOK.get())) {
            return this;
        }
        ((KnowledgeBookMeta) meta).addRecipe(keys);
        return this;
    }

    public ItemBuilder setLeatherColor(Color color) {
        if(isType(ItemSpecial.LEATHER_ARMOR.get())) {
            return this;
        }
        ((LeatherArmorMeta) meta).setColor(color);
        return this;
    }

    public ItemBuilder setPotionColor(Color color) {
        if(isType(ItemSpecial.POTION.get())) {
            return this;
        }
        ((PotionMeta) meta).setColor(color);
        return this;
    }

    public ItemBuilder setBasePotionData(PotionData data) {
        if(isType(ItemSpecial.POTION.get())) {
            return this;
        }
        ((PotionMeta) meta).setBasePotionData(data);
        return this;
    }

    public ItemBuilder addCustomEffect(PotionEffect effect, boolean overwrite) {
        if(isType(ItemSpecial.POTION.get())) {
            return this;
        }
        ((PotionMeta) meta).addCustomEffect(effect, overwrite);
        return this;
    }

    public ItemStack build() {
        this.item.setItemMeta(this.meta);
        return this.item;
    }

    private enum ItemSpecial {

        /**
         * 旗帜
         */
        BANNER("BANNER"),
        /**
         * 知识书
         */
        KNOWLEDGE_BOOK("KNOWLEDGE_BOOK"),
        /**
         * 烟花
         */
        FIREWORK("FIREWORK"),
        /**
         * 药水
         */
        POTION("POTION"),
        /**
         * 皮革
         */
        LEATHER_ARMOR("LEATHER");

        private final String itemName;

        ItemSpecial(String itemName) {
            this.itemName = itemName;
        }

        public String get() {
            return itemName;
        }

    }

    private boolean isType(@NonNull String type) {
        return item.getType().toString().contains(type.toUpperCase());
    }

}
